import type { TableRowSelection as ITableRowSelection, Key } from "antd/lib/table/interface";
import type { ColumnProps } from "antd/lib/table";
import type { PaginationProps } from "./pagination";
import type { FormProps } from "@/components/Form";
import type { RoleEnum } from "@/enums/roleEnum";
import { ReactNode } from "react";

export declare type SortOrder = "ascend" | "descend";

export interface TableCurrentDataSource<T = Recordable> {
	currentDataSource: T[];
}

export interface TableRowSelection<T = any> extends ITableRowSelection<any> {
	/**
	 * Callback executed when selected rows change
	 * @type Function
	 */
	onChange?: (selectedRowKeys: Key[], selectedRows: T[]) => any;

	/**
	 * Callback executed when select/deselect one row
	 * @type Function
	 */
	onSelect?: (record: T, selected: boolean, selectedRows: object[], nativeEvent: Event) => any;

	/**
	 * Callback executed when select/deselect all rows
	 * @type Function
	 */
	onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => any;

	/**
	 * Callback executed when row selection is inverted
	 * @type Function
	 */
	onSelectInvert?: (selectedRows: Key[]) => any;
}

export interface TableCustomRecord<T> {
	record?: T;
	index?: number;
}

export interface ExpandedRowRenderRecord<T> extends TableCustomRecord<T> {
	indent?: number;
	expanded?: boolean;
}
export interface ColumnFilterItem {
	text?: string;
	value?: string;
	children?: any;
}

export interface TableCustomRecord<T = Recordable> {
	record?: T;
	index?: number;
}

export interface SorterResult {
	column: ColumnProps;
	order: SortOrder;
	field: string;
	columnKey: string;
}

export interface FetchParams {
	searchInfo?: Recordable;
	page?: number;
	sortInfo?: Recordable;
	filterInfo?: Recordable;
}

export interface GetColumnsParams {
	ignoreIndex?: boolean;
	ignoreAction?: boolean;
	sort?: boolean;
}

export type SizeType = "default" | "middle" | "small" | "large";

export interface TableActionType {
	reload: (opt?: FetchParams) => void;
	setSelectedRows: (rows: Recordable[]) => void;
	getSelectRows: <T = Recordable>() => T[];
	clearSelectedRowKeys: () => void;
	expandAll: () => void;
	expandRows: (keys: (string | number)[]) => void;
	collapseAll: () => void;
	scrollTo: (pos: string) => void; // pos: id | "top" | "bottom"
	getSelectRowKeys: () => Key[];
	deleteSelectRowByKey: (key: string) => void;
	setPagination: (info: Partial<PaginationProps>) => void;
	setTableData: <T = Recordable>(values: T[]) => void;
	updateTableDataRecord: (rowKey: string | number, record: Recordable) => Recordable | void;
	deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => void;
	insertTableDataRecord: (record: Recordable | Recordable[], index?: number) => Recordable[] | void;
	findTableDataRecord: (rowKey: string | number) => Recordable | void;
	getColumns: (opt?: GetColumnsParams) => BasicColumn[];
	setColumns: (columns: BasicColumn[] | string[]) => void;
	getDataSource: <T = Recordable>() => T[];
	getRawDataSource: <T = Recordable>() => T;
	setLoading: (loading: boolean) => void;
	setProps: (props: Partial<BasicTableProps>) => void;
	redoHeight: () => void;
	setSelectedRowKeys: (rowKeys: Key[]) => void;
	getPaginationRef: () => PaginationProps | boolean;
	getSize: () => SizeType;
	getRowSelection: () => TableRowSelection<Recordable>;
	getCacheColumns: () => BasicColumn[];
	emit?: EmitType;
	updateTableData: (index: number, key: string, value: any) => Recordable;
	setShowPagination: (show: boolean) => Promise<void>;
	getShowPagination: () => boolean;
	setCacheColumnsByField?: (dataIndex: string | undefined, value: BasicColumn) => void;
	setCacheColumns?: (columns: BasicColumn[]) => void;
	updateColumn: (column: BasicColumn | BasicColumn[]) => void;
	setShowForm: (flag: boolean) => void;
	getShowForm: () => boolean;
}

export interface FetchSetting {
	// 请求接口当前页数
	pageField: string;
	// 每页显示多少条
	sizeField: string;
	// 请求结果列表字段  支持 a.b.c
	listField: string;
	// 请求结果总数字段  支持 a.b.c
	totalField: string;
}

export interface TableSetting {
	redo?: boolean;
	form?: boolean;
	size?: boolean;
	setting?: boolean;
	fullScreen?: boolean;
}

export interface BasicTableProps<T = any> {
	// 点击行选中
	clickToRowSelect?: boolean;
	isTreeTable?: boolean;
	// 自定义排序方法
	sortFn?: (sortInfo: SorterResult) => any;
	// 排序方法
	filterFn?: (data: Partial<Recordable<string[]>>) => any;
	// 取消表格的默认padding
	inset?: boolean;
	// 显示表格设置
	showTableSetting?: boolean;
	tableSetting?: TableSetting;
	// 斑马纹
	striped?: boolean;
	// 是否自动生成key
	autoCreateKey?: boolean;
	// 计算合计行的方法
	summaryFunc?: (...arg: any) => Recordable[];
	// 自定义合计表格内容
	summaryData?: Recordable[];
	// 是否显示合计行
	showSummary?: boolean;
	// 是否可拖拽列
	canColDrag?: boolean;
	// 接口请求对象
	api?: (...arg: any) => Promise<any>;
	// 请求之前处理参数
	beforeFetch?: Fn;
	// 自定义处理接口返回参数
	afterFetch?: Fn;
	// 查询条件请求之前处理
	handleSearchInfoFn?: Fn;
	// 请求接口配置
	fetchSetting?: Partial<FetchSetting>;
	// 立即请求接口
	immediate?: boolean;
	// 在开起搜索表单的时候，如果没有数据是否显示表格
	emptyDataIsShowTable?: boolean;
	// 额外的请求参数
	searchInfo?: Recordable;
	// 默认的排序参数
	defSort?: Recordable;
	// 使用搜索表单
	useSearchForm?: boolean;
	// 表单配置
	formConfig?: Partial<FormProps>;
	// 列配置
	columns: BasicColumn[];
	// 是否显示序号列
	showIndexColumn?: boolean;
	// 序号列配置
	indexColumnProps?: BasicColumn;
	actionColumn?: BasicColumn;
	// 文本超过宽度是否显示。。。
	ellipsis?: boolean;
	// 是否继承父级高度（父级高度-表单高度-padding高度）
	isCanResizeParent?: boolean;
	// 是否可以自适应高度
	canResize?: boolean;
	// 自适应高度偏移， 计算结果-偏移量
	resizeHeightOffset?: number;

	// 在分页改变的时候清空选项
	clearSelectOnPageChange?: boolean;
	//
	rowKey?: string | ((record: Recordable) => string);
	// 数据
	dataSource?: Recordable[];
	// 标题右侧提示
	titleHelpMessage?: string | string[];
	// 表格滚动最大高度
	maxHeight?: number;
	// 是否显示边框
	bordered?: boolean;
	// 分页配置
	pagination?: PaginationProps | boolean;
	// loading加载
	loading?: boolean;

	/**
	 * The column contains children to display
	 * @default 'children'
	 * @type string | string[]
	 */
	childrenColumnName?: string;

	/**
	 * Override default table elements
	 * @type object
	 */
	components?: object;

	/**
	 * Expand all rows initially
	 * @default false
	 * @type boolean
	 */
	defaultExpandAllRows?: boolean;

	/**
	 * Initial expanded row keys
	 * @type string[]
	 */
	defaultExpandedRowKeys?: string[];

	/**
	 * Current expanded row keys
	 * @type string[]
	 */
	expandedRowKeys?: string[];

	/**
	 * Expanded container render for each row
	 * @type Function
	 */
	expandedRowRender?: (record?: ExpandedRowRenderRecord<T>) => JSX.Element;

	/**
	 * Customize row expand Icon.
	 * @type Function | VNodeChild
	 */
	expandIcon?: Function | JSX.Element;

	/**
	 * Whether to expand row by clicking anywhere in the whole row
	 * @default false
	 * @type boolean
	 */
	expandRowByClick?: boolean;

	/**
	 * The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0
	 */
	expandIconColumnIndex?: number;

	/**
	 * Table footer renderer
	 * @type Function | VNodeChild
	 */
	footer?: Function | JSX.Element;

	/**
	 * Indent size in pixels of tree data
	 * @default 15
	 * @type number
	 */
	indentSize?: number;

	/**
	 * i18n text including filter, sort, empty text, etc
	 * @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' }
	 * @type object
	 */
	locale?: object;

	/**
	 * Row's className
	 * @type Function
	 */
	rowClassName?: (record: TableCustomRecord<T>, index: number) => string;

	/**
	 * Row selection config
	 * @type object
	 */
	rowSelection?: TableRowSelection;

	/**
	 * Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area.
	 * It is recommended to set a number for x, if you want to set it to true,
	 * you need to add style .ant-table td { white-space: nowrap; }.
	 * @type object
	 */
	scroll?: { x?: number | string | true; y?: number | string };

	/**
	 * Whether to show table header
	 * @default true
	 * @type boolean
	 */
	showHeader?: boolean;

	/**
	 * Size of table
	 * @default 'default'
	 * @type string
	 */
	size?: SizeType;

	/**
	 * Table title renderer
	 * @type Function | ScopedSlot
	 */
	title?: ReactNode | JSX.Element | string | ((data: Recordable) => string);

	/**
	 * Set props on per header row
	 * @type Function
	 */
	customHeaderRow?: (column: ColumnProps, index: number) => object;

	/**
	 * Set props on per row
	 * @type Function
	 */
	customRow?: (record: T, index: number) => object;

	/**
	 * `table-layout` attribute of table element
	 * `fixed` when header/columns are fixed, or using `column.ellipsis`
	 *
	 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
	 * @version 1.5.0
	 */
	tableLayout?: "auto" | "fixed" | string;

	/**
	 * the render container of dropdowns in table
	 * @param triggerNode
	 * @version 1.5.0
	 */
	getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;

	/**
	 * Data can be changed again before rendering.
	 * The default configuration of general user empty data.
	 * You can configured globally through [ConfigProvider](https://antdv.com/components/config-provider-cn/)
	 *
	 * @version 1.5.4
	 */
	transformCellText?: Function;

	/**
	 * Callback executed before editable cell submit value, not for row-editor
	 *
	 * The cell will not submit data while callback return false
	 */
	beforeEditSubmit?: (data: { record: Recordable; index: number; key: string | number; value: any }) => Promise<any>;

	/**
	 * Callback executed when pagination, filters or sorter is changed
	 * @param pagination
	 * @param filters
	 * @param sorter
	 * @param currentDataSource
	 */
	onChange?: (pagination: any, filters: any, sorter: any, extra: any) => void;

	/**
	 * Callback executed when the row expand icon is clicked
	 *
	 * @param expanded
	 * @param record
	 */
	onExpand?: (expande: boolean, record: T) => void;

	/**
	 * Callback executed when the expanded rows change
	 * @param expandedRows
	 */
	onExpandedRowsChange?: (expandedRows: string[] | number[]) => void;

	onColumnsChange?: (data: ColumnChangeParam[]) => void;
}

export type CellFormat =
	| string
	| ((text: string, record: Recordable, index: number) => string | number)
	| Map<string | number, any>;

export interface BasicColumn extends ColumnProps<Recordable> {
	children?: BasicColumn[];
	filters?: {
		text: string;
		value: string;
		children?: unknown[] | (((props: Record<string, unknown>) => unknown[]) & (() => unknown[]) & (() => unknown[]));
	}[];

	//
	flag?: "INDEX" | "DEFAULT" | "CHECKBOX" | "RADIO" | "ACTION";
	customTitle?: JSX.Element;

	slots?: Recordable;

	// 自定义header渲染
	customHeaderRender?: (column: BasicColumn) => string | JSX.Element;
	// Whether to hide the column by default, it can be displayed in the column configuration
	defaultHidden?: boolean;

	// Help text for table column header
	helpMessage?: string | string[] | JSX.Element;

	format?: CellFormat;

	// Editable
	edit?: boolean;
	editRow?: boolean;
	editable?: boolean;
	editComponent?: Object;
	editComponentProps?:
		| ((opt: {
				text: string | number | boolean | Recordable;
				record: Recordable;
				column: BasicColumn;
				index: number;
		  }) => Recordable)
		| Recordable;
	editRule?: boolean | ((text: string, record: Recordable) => Promise<string>);
	editValueMap?: (value: any) => string;
	onEditRow?: () => void;
	// 权限编码控制是否显示
	auth?: RoleEnum | RoleEnum[] | string | string[];
	// 业务控制是否显示
	ifShow?: boolean | ((column: BasicColumn) => boolean);
	// 自定义修改后显示的内容
	editRender?: (opt: {
		text: string | number | boolean | Recordable;
		record: Recordable;
		column: BasicColumn;
		index: number;
	}) => JSX.Element;
	// 动态 Disabled
	editDynamicDisabled?: boolean | ((record: Recordable) => boolean);
}

export interface ColumnChangeParam {
	dataIndex: string;
	fixed: boolean | "left" | "right" | undefined;
	open: boolean;
}

export interface InnerHandlers {
	onColumnsChange: (data: ColumnChangeParam[]) => void;
}

export interface SorterResult {
	column: ColumnProps;
	order: SortOrder;
	field: string;
	columnKey: string;
}
